
import yaml
from pathlib import Path
import cv2

def get_scaled_size(orig_size: tuple, conf_size: tuple) -> tuple:
    """
    根据原视频尺寸和配置参数计算缩放后的宽高
    参数：
        orig_size (tuple): (原始宽, 原始高)
        conf_size (tuple): (配置宽, 配置高)，
                           如果 <= 10 表示缩放比例，如果 > 10 表示实际像素值
    返回：
        (out_w, out_h) -> 缩放后的宽高
    """
    orig_w, orig_h = orig_size
    w_conf, h_conf = conf_size

    # 计算宽度
    if w_conf <= 10:    # 按比例缩放
        out_w = int(orig_w * w_conf)
    else:               # 按像素
        out_w = int(w_conf)

    # 计算高度
    if h_conf <= 10:
        out_h = int(orig_h * h_conf)
    else:
        out_h = int(h_conf)

    print(f"[get_scaled_size] 原始尺寸=({orig_w}x{orig_h}), 配置=({w_conf}, {h_conf}) -> 输出尺寸=({out_w}x{out_h})")
    return out_w, out_h


def load_config(path="../config.yaml"):
    """
    加载 YAML 配置文件
    """
    path = Path(path)
    if not path.is_file():
        raise FileNotFoundError(f"配置文件未找到: {path}")

    with open(path, "r", encoding="utf-8") as f: # 读取配置文件
        cfg = yaml.safe_load(f)

    INPUT_URL  = cfg["INPUT_URL"]       # (str): 读流地址
    SERVER_URL = cfg["SERVER_URL"]      # server_url (str): RTMP/RTSP 推流地址 (如 rtmp://...)
    OUT_WIDTH  = cfg["OUT_WIDTH"]       # width (int): 输出视频宽度（推流）
    OUT_HEIGHT = cfg["OUT_HEIGHT"]      # height (int): 输出视频高度（推流）
    OUT_FPS    = cfg["OUT_FPS"]         # fps (int): 输出帧率（推流）
    BITRATE    = cfg["BITRATE"]         # bitrate (str): 目标码率
    MAXRATE    = cfg["MAXRATE"]         # maxrate (str): 最大码率
    BUFSIZE    = cfg["BUFSIZE"]         # bufsize (str): 缓冲区大小
    PRESET     = cfg["PRESET"]          # preset (str): NVENC 编码预设
    TUNE       = cfg["TUNE"]            # tune (str): 编码优化参数
    CLASSES    = cfg["CLASSES"]         # (list): 用户选的类别列表

    # 读取原视频尺寸
    cap = cv2.VideoCapture(INPUT_URL)
    if not cap.isOpened():
        raise RuntimeError(f"无法打开视频源: {INPUT_URL}")
    orig_size = (
        int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
        int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    )
    cap.release()
    # 读取配置输出视频尺寸
    conf_size = (OUT_WIDTH, OUT_HEIGHT)
    # 配置尺寸解析
    OUT_WIDTH, OUT_HEIGHT = get_scaled_size(orig_size, conf_size)

    command = [
        'ffmpeg',                           # 调用 FFmpeg 程序 本身
        '-y',                               # 自动覆盖已有文件 不用提示确认
        '-f', 'rawvideo',                   # 指定输入格式为 原始视频流
        '-pix_fmt', 'bgr24',                # 输入的像素格式 OpenCV 默认是 BGR 每像素 8bit → bgr24
        '-s', f"{OUT_WIDTH}x{OUT_HEIGHT}",  # 输入帧的分辨率（宽 × 高）必须和 cv2.resize(frame, (OUT_WIDTH, OUT_HEIGHT)) 保持一致
        '-r', str(OUT_FPS),                 # 输入帧率 必须和写入的速度匹配（每秒送多少帧进 stdin）
        '-fflags', '+genpts+discardcorrupt',               # 为没有时间戳（PTS）的输入视频流生成时间戳
        # '-fflags', '+discardcorrupt',       # 输入处理时的 flags，丢弃损坏的帧，而不是尝试解码（避免花屏、马赛克）
        '-i', '-',                          # 输入源是 标准输入（stdin）即 p.stdin.write(frame.tobytes()) 写进去的流

        # '-r', '30',                         # 输出帧率（保持与输入一致也可以直接去掉）
        '-c:v', 'h264_nvenc',               # 视频编码器 使用 NVIDIA GPU 硬件编码（NVENC） 输出 H.264
        '-preset', PRESET,                  # 编码器预设（速度/压缩率平衡）NVENC 新版支持 p1（最快 质量最低）到 p7（最慢 质量最好）
        '-tune:v', TUNE,                    # 编码优化调节  ull（超低延迟） ll（低延迟） hq（高质量）
        '-b:v', BITRATE,                    # 平均目标码率 单位 kbit/s 推流到 RTMP 时码率必须小于你的网络带宽
        '-maxrate', MAXRATE,                # 最大瞬时码率 约束输出码流不要过高 避免卡顿
        '-bufsize', BUFSIZE,                # 缓冲区大小 控制码率波动 和 maxrate 配合使用 一般设置为 maxrate 的 1.5~2 倍
        '-pix_fmt', 'yuv420p',              # 输出像素格式 大多数播放器、RTMP 协议都要求 yuv420p 兼容性最好
        '-g', '10',                         # GOP 长度，10 帧一个关键帧
        '-forced-idr', '1',                 # 确保关键帧是 IDR 帧，观众随时进来都能解码
        '-bsf:v', 'h264_mp4toannexb',       # 把 H.264 流从 MP4/AVC 格式（length-prefixed）转换成 Annex B 格式（start code 前缀 0x00000001）
        '-f', 'flv',                        # 输出封装格式 RTMP 协议要求使用 flv 封装格式
        SERVER_URL                          # 推流地址：RTMP 服务器地址 + 推流密钥/频道名
    ]
    # cmd = "ffmpeg -y -f rawvideo -pix_fmt bgr24 -s 640x360 -r 15 -i - -c:v h264_nvenc -preset p1 -tune:v ll -b:v 4000k -maxrate 6000k -bufsize 8000k -pix_fmt yuv420p -f flv rtmp://192.168.0.222/live/uavid/"

    return command, INPUT_URL, CLASSES, OUT_WIDTH, OUT_HEIGHT, OUT_FPS
